<?php
namespace app\common\model;
use think\Db;
use think\Loader;

class Game2
{

    public function getGame($gameId){
        if(!empty($gameId)&&is_numeric($gameId)){
            $key='game:'.$gameId;
            $redis=new Redis();
            $game=$redis->hGetAll($key);
            $ttl=config('game_ttl');
            if(empty($game)){
                $game=Db::name('view_game_manage')
                    ->where(['game_id'=>$gameId])
                    ->find();
                if(!empty($game)){
                    $redis->hMset($key,$game);
                    $redis->expire($key,$ttl);
                }else{
                    return false;
                }
            }
            return $game;
        }else{
            return false;
        }
    }



    /**
     * 获取游戏下载地址
     * @param $cpsId
     * @param $gameId
     * @return mixed|string
     */
    public function getUrl($cpsId,$gameId){
        $rs=Db::name('channel_game')->where(['channel_id'=>$cpsId,'game_id'=>$gameId])->find();
        if($rs){
            return $rs['download'];
        }else{
            return '';
        }
    }



    /**
     * 获取标签id,没有就添加
     * @param $name
     * @return bool|int|mixed|string
     */
    public function getTagId($name){
        $name=trim($name);
        if(empty($name)){
            return false;
        }
        $redis=new Redis();
        $tags=$redis->hGetAll('game:tags');
        if($tags){//有缓存
            foreach($tags as $k=>$v){
                if($v==$name){
                    return $k;//缓存里有
                }
            }
            //缓存里没有,先存数据库再缓存
            $id=$this->_saveTagToDb($name);
            if($id){
                $redis->hSet('game:tags',$id,$name);
                return $id;
            }else{
                return false;
            }

        }else{
            $id=$this->_saveTagToDb($name);

            $rs=Db::name('game_tag')->select();
            $tags=[];
            if($rs){
                foreach($rs as $k=>$v){
                    $tags[$k]=$v;
                }
                $redis->hMset('game:tags',$tags);
            }
            if($id){
                return $id;
            }else{
                return false;
            }

        }
    }

    /**
     * 获取游戏标签的并集,查相似游戏时使用
     * @param $tagStr
     * @return array
     */
    public function getTagUnion($tagStr){
        if(empty($tagStr)){
            return [];
        }
        $tagArr=explode(',',$tagStr);
        foreach($tagArr as $k=>$v){
            $tagArr[$k]='tags:'.$v;
        }
        $redis=new Redis();
        $this->_cacheAllTags();
        return $redis->sUnion($tagArr);
    }
    /**
     * 保存标签到数据库,有就直接返回,没有就添加
     * @param $name
     * @return int|mixed|string
     */
    private function _saveTagToDb($name){
        $rs=Db::name('game_tag')
            ->where(['name'=>$name])
            ->find();
        if($rs){
            return $rs['id'];
        }else{
            return Db::name('game_tag')->insert(['name'=>$name]);
        }
    }

    /**
     * 缓存游戏标签集合
     */
    private function _cacheAllTags(){
        $redis=new Redis();
        $games=$this->getGamePublishs();
        foreach ($games as $v) {
            if(!empty($v['tags'])){
                $arr=explode(',',$v['tags']);
                foreach ($arr as $item) {
                    $redis->sAdd('tags:'.$item,$v['id'].','.$v['game_id']);
                }
            }
        }
    }

    /**
     * 获取game_publish及扩展信息
     * @param string $id
     * @param string $gameId
     * @return array|false|\PDOStatement|string|\think\Collection|\think\Model
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function getGamePublishs($id='',$gameId=''){
        if(!empty($id)){
            $game=Db::name('view_publish')
                ->where(['id'=>$id])
                ->find();
        }elseif(!empty($gameId)){
            $game=Db::name('view_publish')
                ->where(['game_id'=>$gameId])
                ->find();
        }else{
            $game=Db::name('view_publish')
                ->select();
        }
        return $game;
        /*
        $redis=new Redis();
        if(!$redis->exists('game:view_publish')){
            $games=Db::name('view_publish')->select();
            $publish=[];
            if($games){
                foreach ($games as $g) {
                    $publish[$g['id']]=json_encode($g);
                }
                $redis->hMset('game:view_publish',$publish);
                $redis->expire('game:view_publish',config('game_publish_ttl'));
            }else{
                return [];
            }
        }
        if($id){
            $publish=$redis->hGet('game:view_publish',$id);
            if($publish){
                return json_decode($publish,true);
            }else{
                return [];
            }
        }else{
            $publish=$redis->hGetAll('game:view_publish');
            $ret=[];
            foreach($publish as $k=>$v){
                $ret[$k]=json_decode($v,true);
            }
            return $ret;
        }*/

    }

    /**
     * @param $myOrderId
     * @param string $type
     * @return array
     * @throws \think\Exception
     */
    public function gameNotify($myOrderId,$type='manual'){
        //return $this->_gameNotify($myOrderId);
        if(empty($myOrderId)){
            return err('订单号不能为空',['echo'=>'订单号为空无法操作','params'=>'']);
        }
        $redis=Loader::model('\\app\\common\\model\\Redis');
        $key='gamenotify:'.$myOrderId;
        $Order=Loader::model('\\app\\common\\model\\Order');
        $order=$Order->getOrder($myOrderId);
        if(empty($order))return err('订单号不存在',['echo'=>'订单号不存在','params'=>'']);
        $order_status=[
            'status'=>'fail',
            'lock_time'=>time(),
            'game_notify_failed'=>$order['game_notify_failed']
        ];
        if(!$redis->exists($key)){
            $redis->hMset($key,$order_status,86400);
            $rs=$this->_gameNotify($myOrderId);

            if(check($rs)){
                $redis->hSet($key,'status','success');
            }else{
                //增加失败次数
                $table=get_order_table($myOrderId);
                Db::name($table)
                    ->where(['my_order_id'=>$myOrderId])
                    ->setInc('game_notify_failed');
                $redis->hIncrBy($key,'game_notify_failed',1);
            }
            return $rs;
        }else{
            $order=$redis->hGetAll($key);
            $now=time();
            $game_notify_failed=$redis->hGet($key,'game_notify_failed');
            if($order['status']=='fail'&&$now-$order['lock_time']>60&&$game_notify_failed<5){
                $redis->hSet($key,'lock_time',time(),86400);
                $rs=$this->_gameNotify($myOrderId);

                if(check($rs)){
                    $redis->hSet($key,'status','success');
                }else{
                    //增加失败次数
                    $table=get_order_table($myOrderId);
                    Db::name($table)
                        ->where(['my_order_id'=>$myOrderId])
                        ->setInc('game_notify_failed');
                    $redis->hIncrBy($key,'game_notify_failed',1);
                }
                return $rs;
            }else{
                if($type=='manual'){//如果是手动操作,不限定次数
                    return $this->_gameNotify($myOrderId);
                }else{
                    return err('超过通知次数限制',['echo'=>'超过通知次数限制','params'=>'']);
                }
            }
        }

    }
    private function _testNotify(){
        sleep(30);
        return err('error');
    }
    private function _gameNotify($myOrderId){

        $table=get_order_table($myOrderId);
        $data=[
            'game_result'=>1,
            'game_time'=>time()
        ];
        $Order=Loader::model(config('order_model'));
        $order=$Order->getOrder($myOrderId);
        if(!empty($order)){
            if($order['game_result']==1){
                return suc();
            }
        }else{
            return err('game_notify:订单不存在');
        }
        $clientId=$order['client_id'];
        $gameId=isset($order['game_id'])?$order['game_id']:'';
        $serverId=isset($order['server_id'])?$order['server_id']:'';
        $callback=$this->getCallback($gameId,$serverId,'pay',$clientId)?:'';
        $secret=$this->getField($gameId,'secret')?:'';
        if(!$callback){
            return err('game_notify:游戏回调地址为空');
        }

        $ver=$this->getField($gameId,'sdk_version');

        if($clientId==107){
            if($gameId==1176){
                $ver='v2.0';
            }
            //$ver='v1.0';
        }
        /*if($gameId==1246||$gameId==1248){
            $ver='v2.0';
        }else{
            $ver='v1.0';
        }*/
        if(($gameId==1257||$gameId==1234||$gameId==1266||$gameId==1278)&&$order['my_user_id']<=config('sdk2_start_id_index')){
            $User=Loader::model('\\app\\common\\model\\User');
            $user=$User->findUserById($order['my_user_id'],$order['channel_id']);

            if(!check($user))return err('用户id错误');
            $order['my_user_id']=$user['sdkdrive_id'];
        }

        $params=[];
        if($ver=='v1.0'){
            $params = array(
                'order_id'        => $order['my_order_id'],
                'user_id'        => $order['my_user_id'],
                'role_id'        => $order['role_id'],
                'amount'         => $order['total_price']/100,//转为元
                'game_coin'      => $order['coin'],
                'cp_order_id'      => $order['cp_order_id'],
                'success'        => 1,
            );
            ksort($params);
            $string = '';
            foreach($params as $key=>$value){
                $string .= $key . "=" . $value . "&";
            }
            $signString = substr($string, 0, -1);
            $signature =  md5("{$signString}:{$secret}");
            $params['sign'] = $signature;
            if($gameId==1149){//血色城堡 = 和|的替换问题，特殊处理------------------------------------------------------------
                $params['ext'] = str_replace("=","|",$order['ext']);
            }else{
                $params['ext'] = $order['ext'];
            }

            if($gameId==1152){//银河战姬的充值回调放在扩展参数里--------------------------------------------------------------
                $ext=json_decode($order['ext'],true);
                $serverId=$ext['sid'];
                switch($serverId){
                    case '1501':
                        $game_data['callback']='http://gundacn.sudogame.com/charge/miyucallback';
                        break;
                    case '1502':
                        $game_data['callback']='http://gundacn2.sudogame.com/charge/miyucallback';
                        break;
                    case '1503':
                        $game_data['callback']='http://gundacn3.sudogame.com/charge/miyucallback';
                        break;
                    case '1504':
                        $game_data['callback']='http://gundacn4.sudogame.com/charge/miyucallback';
                        break;
                    case '1505':
                        $game_data['callback']='http://gundacn5.sudogame.com/charge/miyucallback';
                        break;
                    case '1506':
                        $game_data['callback']='http://gundacn6.sudogame.com/charge/miyucallback';
                        break;
                    case '1507':
                        $game_data['callback']='http://gundacn7.sudogame.com/charge/miyucallback';
                        break;
                    case '1508':
                        $game_data['callback']='http://gundacn8.sudogame.com/charge/miyucallback';
                        break;
                    case '1509':
                        $game_data['callback']='http://gundacn9.sudogame.com/charge/miyucallback';
                        break;
                    case '1510':
                        $game_data['callback']='http://gundacn10.sudogame.com/charge/miyucallback';
                        break;
                    default:
                        $game_data['callback']=$ext['url'].'/charge/miyucallback';
                }

            }
            Log::write(json_encode($params),'log','gamenotify');
            Log::write("{$signString}:",'log','gamenotify');
        }
        if($ver=='v2.0'){
            $params = array(
                'game_id'   =>$order['game_id'],
                'my_order_id'        => $order['my_order_id'],
                'my_user_id'        => $order['my_user_id'],
                'role_id'        => $order['role_id'],
                'server_id'     =>$order['server_id'],
                'total_price'         => $order['total_price'],//分
                'game_coin'      => $order['coin'],
                'cp_order_id'      => $order['cp_order_id'],
                'pay_time'        => $order['pay_time'],
                'notify_time'      =>time(),
                'ext'=>$order['ext']
            );
            ksort($params);
            $string = '';
            foreach($params as $key=>$value){
                $string .= $key . "=" . $value . "&";
            }
            $string = substr($string, 0, -1);
            $string.=':'.$secret;
            $signature =  md5($string);
            $params['sign'] = $signature;
        }

        if(!$params){
            return err('game_notify:接口版本号错误');
        }



        if(config('game_notify_debug')){
            $res=$this->_testNotify();
        }else{
            $res=Http::post($callback,$params);
        }
        Log::write('time:'.date('H:i:s').'|callback:'.$callback.'|postParams:'.json_encode($params).'|postRs:'.json_encode($res).'|[input]:'.json_encode(input()),'log','gamenotify');
        if($res['result']==1){
            $res['data'] = str_replace("\n", "", $res['data']);
            //Log::write(json_encode($res),'log','game-noti');
            if(is_array($res['data'])){
                return err('game_notify:返回错误',['echo'=>$res['data'],'params'=>$params]);
            }
            if(strtolower($res['data'])=='success'){
                try{
                    Db::name($table)
                        ->where(['my_order_id'=>$myOrderId])
                        ->update($data);
                    return suc('game_notify:成功',['echo'=>'game_notify:成功','params'=>$params]);
                }catch(\Exception $e){
                    Log::record('gameNotify|'.json_encode($res));
                    return err('game_notify:数据更新异常',['echo'=>$e->getMessage(),'params'=>$params]);
                }
            }else{
                Log::record('gameNotify|'.json_encode($res));
                return err('game_notify:通知失败',['echo'=>$res['data'],'params'=>$params]);
            }

        }else{
            return err('game_notify:接口错误',['echo'=>$res['msg'],'params'=>$params]);
        }

    }

    public function getCallback($gameId,$serverId='',$type='pay',$clientId=''){
        if(empty($gameId)||empty($serverId)){
            return false;
        }
        //回合三国 ios越狱 测试地址特殊处理

        if($gameId==1176&&$clientId==107){
            //return "http://120.27.34.43:8082/PayMiyuYJ.do";
            return 'http://sync.1sdk.cn/cb/ios/miyu/0401CFB5E8E75F5A/sync.html';
        }

        $rs=Db::name('view_game')
            ->field('pay_callback,gm_callback,rebate_callback,third_pay_callback')
            ->where(['game_id'=>$gameId])
            ->find();
        if(empty($rs)){
            return false;
        }else{
            switch($type){
                case 'pay':
                    /*$clientId=input('clientId','');
                    switch($clientId){
                        case 101:
                            return $rs['third_pay_callback'];
                    }*/

                    return $rs['pay_callback'];
                    break;
                case 'gm':
                    return $rs['gm_callback'];
                    break;
                case 'rebate':
                    return $rs['rebate_callback'];
                    break;
                default:
                    return false;
            }
        }


    }


    /**
     * 获取任意字段
     * @param $gameId
     * @param $field
     * @return mixed|string
     */
    public function getField($gameId,$field){
        $ret='';
        if(empty($gameId)||empty($field)){
            return false;
        }
        $redis=new Redis();
        if($redis->exists('game:'.$gameId)){
            $ret=$redis->hGet('game:'.$gameId,$field);
        }else{
            $game=$this->getGame($gameId);
            if($game){
                $ret=$game[$field];
            }
        }
        return $ret;

    }

    public function checkIp($gameId,$ip){
        $ipList=$this->getField($gameId,'server_ip');
        if(strpos($ipList,$ip)!==false){
            return true;
        }else{
            return false;
        }
    }

    public function gameNotice(){
        $id = Db::name('Notice')->where('prompt', 1)->value('id');
        $url =  $id ? 'http://uc.miyuhaiwai.com/Account/noticeDetail?ntId='.$id : '';
        return $url;
    }

    public function download($gameId,$cpsId,$channelId,$clientId){

        $Download=Db::name('download');
        $rs=$Download->where(['game_id'=>$gameId,'cps_id'=>$cpsId])->find();
        if($rs){
            $Download->where(['game_id'=>$gameId,'cps_id'=>$cpsId])->setInc('downloads');
        }else{
            $Download->insert(['game_id'=>$gameId,'cps_id'=>$cpsId,'channel_id'=>$channelId,'downloads'=>1,'client_id'=>$clientId]);
        }
        return suc();
    }

    public function downStat($gameId){
        $game=Db::name('game_extend')->where(['game_id'=>$gameId])->field('download_base')->find();
        if(empty($game)){
            $base=0;
        }else{
            $base=$game['download_base'];
        }
        $Download=Db::name('download');
        $rs=$Download->where(['game_id'=>$gameId])->sum('downloads');
        $ret=(int)$base+(int)$rs;
        return $ret;
    }

    public function isPayClosed($gameId){
        $chargeTimeRegion=$this->getField($gameId,'charge_time_region');
        list($start,$end)=explode('-',$chargeTimeRegion);
        $now=time();
        if($now<$start||$now>$end){
            return true;
        }else{
            return false;
        }
    }

    public function delCache($gameId){
        if(empty($gameId))return false;
        $redis=Loader::model('\\app\\common\\model\\Redis');
        return $redis->delete('game:'.$gameId);
    }

    /**
     * 更新游戏
     * @param $gameId
     * @param array $fields
     * @return int|string
     * @throws \think\Exception
     * @throws \think\exception\PDOException
     */
    public function update($gameId,array $fields){
        unset($fields['game_id']);
        $rs=Db::name('game')
            ->where(['game_id'=>$gameId])
            ->update($fields);
        if($rs){
            $redis=Loader::model('\\app\\common\\model\\Redis');
            $redis->delete('game:'.$gameId);
        }

        return $rs;
    }

}



